﻿#region Copyright RenGuiYou. All rights reserved.
//=====================================================
// NeatlyFrameWork
// Author:      RenGuiyou
// Feedback: 	mailto:750539605@qq.com
//=====================================================
#endregion

using System;
using Neatly.Module;
using Neatly.Timer;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace Neatly.Load.Manager
{
    public class SceneLoadManager : Singleton<SceneLoadManager>
    {
        private LoadModule m_LoadModule;
        private AsyncOperation m_AsyncOperation;
        private Action<float> m_OnProgressAction;
        private Action m_OnCompletedAction;
        private string m_lastSceneName;

        public void Init(LoadModule loadModule)
        {
            m_LoadModule = loadModule;
        }

        public async void LoadScene(string sceneName, Action<float> progress, Action action)
        {
            string bundleSceneName = $"scene_{sceneName}";
#if UNITY_EDITOR
            if (NeatlyConfig.AssetBundleEnable)
#endif
            {
                var loader = await m_LoadModule.LoadAssetBundle(bundleSceneName);
                loader.AddReferenceCount();
            }
            ExecuteLoadScene(sceneName, progress, action);
            Resources.UnloadUnusedAssets();
#if UNITY_EDITOR
            if (NeatlyConfig.AssetBundleEnable)
#endif
            {
                if (!string.IsNullOrEmpty(m_lastSceneName))
                {
                    Loader lastLoader = m_LoadModule.GetLoader(m_lastSceneName);
                    lastLoader?.LoseReferenceCount();
                }
            }
            GC.Collect();
            m_lastSceneName = bundleSceneName;
        }

        private void ExecuteLoadScene(string sceneName, Action<float> progress, Action action)
        {
            m_OnProgressAction = progress;
            m_OnCompletedAction = action;
            m_AsyncOperation = SceneManager.LoadSceneAsync(sceneName);
            if (m_OnCompletedAction != null)
            {
                NeatlyTimer.AddFrame(this, FrameUpdate);
            }
        }

        private void FrameUpdate(float dt)
        {
            if (m_AsyncOperation == null)
            {
                return;
            }
            if (m_AsyncOperation.isDone)
            {
                m_OnCompletedAction();
                m_OnCompletedAction = null;
                m_OnProgressAction = null;
                NeatlyTimer.Remove(this, FrameUpdate);
            }
            else
            {
                m_OnProgressAction?.Invoke(m_AsyncOperation.progress);
            }
        }
    }
}